package tools.neoBio;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;

import neuro.uu.se.utils.Utils;

import tools.Jalview.Feature;
import tools.Jalview.FeatureFileGenerator;
import tools.fasta.FastaSeq;
import tools.fasta.fastaParser;

public class neoBioUtils {

	private static String sep="\t";

	public static void main(String[] args) throws Exception{
		if(args.length>0){
			if(args[0].equals("conservedNeedle")&&args.length==5){
				conservedNeedle(args[1],args[2],args[3],args[4]);
			}else if(args[0].equals("max")&&args.length==2){
				//Another cmd
			}else{
				System.err.println(printHelp());
				System.exit(616);
			}
		}else{
			System.err.println(printHelp());
			System.exit(616); 
		}
		
		System.err.println("Done!");
		System.exit(0);
	}
	private static String printHelp(){
		String help="Usage: neoBioUtils <cmd> <input>\n";
		help+="where <cmd> is:\n";
		help+="conservedNeedle - Aligns all sequences in the first file towards all in the second file. Calculates the number of times a position is conserved.\n";
		help+="\t<input> = <Matrix> <fa-file 1> <fa-file 2> <outprefix>\n";
		
		
		
		return help;
	}
	
	public static void conservedNeedle(String Matrix,String file1, String file2, String outprefix)throws Exception{
		fastaParser fp =new fastaParser(new BufferedReader(new FileReader(file2)));
		ArrayList<FastaSeq> seq1=new ArrayList<FastaSeq>(),seq2= new ArrayList<FastaSeq>();
		int max1=0,max2=0;
		System.err.println("Reading data...");
		for(;fp.hasNext();){
			seq2.add(fp.next());
			max2++;
		}
		fp= new fastaParser(new BufferedReader(new FileReader(file1)));
		for(;fp.hasNext();){
			seq1.add(fp.next());
			max1++;
		}
		System.err.println("Aligning...");
		ArrayList<ArrayList<HashMap<String, HashMap<Integer, Integer>>>> res=Utils.forEachCollectionObject(new alignNeedle(seq2,Matrix), seq1);
		
//		FastaSeq one;
//		PairwiseAlignment pa;
//		String s1,s2,tag;
//		int pos1,pos2;
//		NeedlemanWunsch nw= new NeedlemanWunsch();
//		nw.setScoringScheme(new ScoringMatrix(new FileReader(Matrix)));
//		HashMap<String, HashMap<Integer, Integer>> res1= new HashMap<String, HashMap<Integer,Integer>>();
//		HashMap<String, HashMap<Integer, Integer>> res2= new HashMap<String, HashMap<Integer,Integer>>();
		
//		for(;fp.hasNext();){
//			one=fp.next();
//			max1++;
//			if(max1%10==0){
//				System.out.println(max1);
//			}
//			for (FastaSeq two : seq2) {
//				nw.loadSequences(new StringReader(one.getSeq()), new StringReader(two.getSeq()));
//				pa=nw.getPairwiseAlignment();
//				nw.unloadSequences();
//				// analyze the alignment pa
//				s1=pa.getGappedSequence1();
//				s2=pa.getGappedSequence2();
//				tag=pa.getScoreTagLine();
//				pos1=-1; //first position is 0
//				pos2=-1;
//				for(int i=0;i<tag.length();i++){
//					if(s1.charAt(i)!=' '){
//						pos1++;
//					}
//					if(s2.charAt(i)!=' '){
//						pos2++;
//					}
//					if(tag.charAt(i)!=' '){
//						//res1
//						if(!res1.containsKey(one.getQname())){
//							res1.put(one.getQname(), new HashMap<Integer, Integer>());
//						}
//						if(res1.get(one.getQname()).containsKey(pos1)){
//							res1.get(one.getQname()).put(pos1, res1.get(one.getQname()).get(pos1)+1);
//						}else{
//							res1.get(one.getQname()).put(pos1, 1);
//						}
//						//res2
//						if(!res2.containsKey(one.getQname())){
//							res2.put(two.getQname(), new HashMap<Integer, Integer>());
//						}
//						if(res2.get(two.getQname()).containsKey(pos2)){
//							res2.get(two.getQname()).put(pos2, res2.get(two.getQname()).get(pos2)+1);
//						}else{
//							res2.get(two.getQname()).put(pos2, 1);
//						}
//					}
//				}
//			}
//		}
		
		//create jalview-file
		int nrOfBins=10;
		FeatureFileGenerator ffg =new FeatureFileGenerator();
		BufferedWriter out =new BufferedWriter(new FileWriter(outprefix+"_1.jalview"));
		ArrayList<Feature> out1= new ArrayList<Feature>();
		HashMap<String, HashMap<Integer, Integer>> res2= new HashMap<String, HashMap<Integer,Integer>>();
		System.err.println("merging results...");
		
		for (ArrayList<HashMap<String,HashMap<Integer,Integer>>> list : res) {
			HashMap<String, HashMap<Integer, Integer>> res1= list.get(0);
			HashMap<String, HashMap<Integer, Integer>> tmp2= list.get(1);
			out1.addAll(hmToFeatureList(res1, max2, nrOfBins));
			for (String qname : tmp2.keySet()) {
				if(!res2.containsKey(qname)){
					res2.put(qname, new HashMap<Integer, Integer>());
				}
				
				for (Integer pos2 : tmp2.get(qname).keySet()) {
					if(res2.get(qname).containsKey(pos2)){
//						System.err.println(""+tmp2.get(qname).get(pos2));
						res2.get(qname).put(pos2, res2.get(qname).get(pos2)+tmp2.get(qname).get(pos2));
					}else{
						res2.get(qname).put(pos2, tmp2.get(qname).get(pos2));
					}
				}
			}
		}
		//print out1 och hmToFeatureList(res2, max2, nrOfBins);
		System.err.println("\tstep 2..");
		ArrayList<Feature> out2 =hmToFeatureList(res2, max1, nrOfBins);
		System.err.println("out1: "+out1.size());
		System.err.println("out2: "+out2.size());
		
		System.err.println("print file 1");
		ffg.FeatureToFile(out1, out);
		out.close();
		System.out.println("print file 2");
		out = new BufferedWriter(new FileWriter(outprefix+"_2.jalview"));
		ffg.FeatureToFile(out2, out);
		out.close();
		
		
		
		
		
		
////		ArrayList<Integer> used;
//		for (String qname : res1.keySet()) {
//			HashMap<Integer, Integer> tmp = res1.get(qname);
//			for (Integer key : tmp.keySet()) {
//				out1.add(new Feature(tmp.get(key)+"/"+max1,qname,"G"+tmp.get(key)*nrOfBins/max1,"",-1,key,key));
//			}
//			
////			used= new ArrayList<Integer>();
////			for (Integer key : tmp.keySet()) {
////				if(!used.contains(key)){
////					out1.add(expandFeture(key, tmp, used,max1,qname));
////				}
////			}
//		}
//		out.write(ffg.FeatureString(out1));
//		out.close();
//		
//		ArrayList<Feature> out2= new ArrayList<Feature>();
//		out = new BufferedWriter(new FileWriter(outprefix+"_2.jalview"));
//		for (String qname : res2.keySet()) {
//			HashMap<Integer, Integer> tmp = res2.get(qname);
//			for (Integer key : tmp.keySet()) {
//				out1.add(new Feature(tmp.get(key)+"/"+max2,qname,"G"+tmp.get(key)*nrOfBins/max2,"",-1,key,key));
//			}
//			
////			used= new ArrayList<Integer>();
////			for (Integer key : tmp.keySet()) {
////				if(!used.contains(key)){
////					out2.add(expandFeture(key, tmp, used,max2,qname));
////				}
////			}
//		}
//		out.write(ffg.FeatureString(out2));
//		out.close();
	}
	
	private static ArrayList<Feature> hmToFeatureList(HashMap<String, HashMap<Integer, Integer>> res, int max, int nrOfBins){
		ArrayList<Feature> out= new ArrayList<Feature>();
		for (String qname : res.keySet()) {
			HashMap<Integer, Integer> tmp = res.get(qname);
			for (Integer key : tmp.keySet()) {
				out.add(new Feature(tmp.get(key)+"/"+max,qname,"G"+tmp.get(key)*nrOfBins/max,"",-1,key,key));
			}
		}
		return out;
	}
	
	private static Feature expandFeture(Integer key,HashMap<Integer, Integer> tmp,ArrayList<Integer>used,int max,String qname){
		used.add(key);
		int nrOfBins=10;
		int start=key,stop=key,c=tmp.get(key)*nrOfBins/max;
		//expand downstream
		for(;!used.contains(start-1)&&tmp.containsKey(start-1);start--){
			if(tmp.get(start-1)*nrOfBins/max==c){
				used.add(start-1);
			}
		}
		//expand upstream
		for(;!used.contains(stop+1)&&tmp.containsKey(stop+1);stop++){
			if(tmp.get(stop+1)*nrOfBins/max==c){
				used.add(stop+1);
			}
		}
		return new Feature(tmp.get(key)+"/"+max,qname,"G"+c,"",-1,start,stop);
	}
}
